#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/list.h>
#include <linux/spi/spi.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include <linux/poll.h>

struct spi_transfer t;
struct spi_device *bmi_dev;

static int major;
static struct class *bmi_class;
static unsigned char tx_data[10];
static unsigned char rx_data[10];

/**
 * @brief   bmi 文件读取接口
 * @param   file: 文件
 * @param   buf: 用于存储传回读取数据的变量地址
 * @param   size: 需要读取的字节数+1
 * @param   offset: 未使用，传入参数无效
 * @return  0
 */
static ssize_t bmi_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{
	int err;

	// struct spi_transfer msgs[2];
	// printk("%s %s %d\n",__FILE__, __FUNCTION__, __LINE__);
	
	if(size == 7){// 使用 bmi088 连续读取模式，输入首地址，一次将后面 6 个数据全读出来，效率更高
		t.len = 7;
		err = copy_from_user(tx_data, buf, 7);
		// printk("copy from usr:0x%x\n", tx_data[0]);

		err = spi_sync_transfer(bmi_dev, &t, 1);

		err = copy_to_user(buf, rx_data, 7);
		// printk("rx_data(h):0x%x 0x%x\n", rx_data[0], rx_data[1]);
		// printk("rx_data(d):%d %d\n", rx_data[0], rx_data[1]);
		t.len = 2;
	}else {// 单字节读取，每次需要输入寄存器地址
		err = copy_from_user(tx_data, buf, 2);
		// printk("copy from usr:0x%x 0x%x\n", tx_data[0], tx_data[1]);
		
		err = spi_sync_transfer(bmi_dev, &t, 1);

		err = copy_to_user(buf, rx_data, 2);
		// printk("rx_data(h):0x%x 0x%x\n", rx_data[0], rx_data[1]);
		// printk("rx_data(d):%d %d\n", rx_data[0], rx_data[1]);
	}

	return 0;
}

/**
 * @brief   bmi 文件写入接口
 * @param   file: 文件
 * @param   buf: 需要发送的数据的变量地址
 * @param   size: 未使用，传入参数无效
 * @param   offset: 未使用，传入参数无效
 * @return  0
 */
static ssize_t bmi_write(struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
	int err;
	// unsigned char ker_buf[2];

	// printk("%s %s %d\n",__FILE__, __FUNCTION__, __LINE__);
	// memset(&t, 0, sizeof(t));

	/* copy_from_user  */
	err = copy_from_user(tx_data, buf, 1);
	// printk("copy from usr:0x%x 0x%x\n", tx_data[0], tx_data[1]);

	err = spi_sync_transfer(bmi_dev, &t, 1);

	//spidata = ker_buf[1];

	// printk("rx_data(h):0x%x 0x%x\n", rx_data[0], rx_data[1]);
	// printk("rx_data(d):%d %d\n", rx_data[0], rx_data[1]);
	
	return 0;    
}

/* 定义自己的 file_operations 结构体 */
static struct file_operations bmi_fops = {
	.owner	 = THIS_MODULE,
	//.unlocked_ioctl = bmi_ioctl,
	.read    = bmi_read,
	.write   = bmi_write,
	//.poll    = bmi_poll,
	//.fasync  = bmi_fasync,
};

static int bmi_probe(struct spi_device *spi){
	printk("%s %s %d\n",__FILE__, __FUNCTION__, __LINE__);

	bmi_dev = spi_dev_get(spi);
	/* register_chrdev */
	major = register_chrdev(0, "bmi088", &bmi_fops);  

	/* class_create */
	bmi_class = class_create(THIS_MODULE, "bmi_class");

	/* device_create */
	device_create(bmi_class, NULL, MKDEV(major, 0), NULL, "bmi088");

	/* 初始化 spi_transfer */
	t.tx_buf = tx_data;
	t.rx_buf = rx_data;
	t.len    = 2;
	t.bits_per_word = 8;
	t.tx_nbits = SPI_NBITS_SINGLE;
	t.rx_nbits = SPI_NBITS_SINGLE;	

    return 0;
}

static int bmi_remove(struct spi_device *spi){
	printk("%s %s %d\n",__FILE__, __FUNCTION__, __LINE__);

	device_destroy(bmi_class, MKDEV(major, 0));
	class_destroy(bmi_class);
	unregister_chrdev(major, "bmi088");

    return 0;
}

// 这个好像可以不要，懒得管了，能用就行
static const struct spi_device_id bmi_id_table[] = {
	{ "bmi088", },
	{ }
};

static const struct of_device_id bmi_of_match[] = {
	{.compatible = "bmi,bmi088", },
	{}
};


static struct spi_driver bmi_driver = {
	.driver  = {
		.name   = "bmi088",
		.owner = THIS_MODULE,
		.of_match_table = bmi_of_match,
	},
	.id_table = bmi_id_table,
	.probe  = bmi_probe,
	.remove = bmi_remove,
};

module_spi_driver(bmi_driver);

MODULE_AUTHOR("TiX");
MODULE_DESCRIPTION("bmidriver");
MODULE_LICENSE("GPL");
